package com.icloud.article.boot.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.icloud.article.boot.dao.UpvoteDao;
import com.icloud.article.boot.dto.UpvotePageDto;
import com.icloud.article.boot.mapper.UpvoteMapper;
import com.icloud.article.boot.model.Collect;
import com.icloud.article.boot.model.Discuss;
import com.icloud.article.boot.model.Upvote;
import com.icloud.article.boot.service.ArticleService;
import com.icloud.article.boot.service.DiscussService;
import com.icloud.article.boot.service.UpvoteService;
import com.icloud.article.boot.vo.ArticleVo;
import com.icloud.article.boot.vo.CollectVo;
import com.icloud.article.boot.vo.StatisticsVo;
import com.icloud.common.core.api.ResultCode;
import com.icloud.common.database.enums.BusinessTypeEnum;
import com.icloud.common.database.model.Article;
import com.icloud.common.web.exception.ApiException;
import com.icloud.common.web.util.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


/**
 * 点赞service 实现类
 */
@Service
public class UpvoteServiceImpl extends ServiceImpl<UpvoteMapper, Upvote> implements UpvoteService {
    @Autowired
    private UpvoteDao upvoteDao;
    @Autowired
    private AuthUtil authUtil;
    @Autowired
    private ArticleService articleService;
    @Autowired
    private DiscussService discussService;


    /**
     * 根据帖子查询点赞数量
     * @param businessType 业务类型，ARTICLE,DISCUSS
     * @param businessIds 业务id
     * @return key:业务id value:点赞数量
     */
    @Override
    public Map<Long, Long> queryUpvoteCount(String businessType,List<Long> businessIds) {

        List<StatisticsVo> statisticsVos = upvoteDao.queryUpvoteCountByArticle(new LambdaQueryWrapper<Upvote>()
                .eq(Upvote::getBusinessType, businessType)
                .in(Upvote::getBusinessId, businessIds)
                .groupBy(Upvote::getBusinessId));

        if(CollectionUtil.isEmpty(statisticsVos)){
            return new HashMap<>();
        }
        return statisticsVos.stream().collect(Collectors.toMap(StatisticsVo::getArticleId, StatisticsVo::getCount));

    }


    /**
     * 点赞
     * @param businessType 业务类型，ARTICLE,DISCUSS
     * @param businessId 业务id
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void upvote(String businessType,Long businessId) {
        Long loginId = authUtil.getUserId();

        long count = count(new LambdaQueryWrapper<Upvote>()
                .eq(Upvote::getBusinessId, businessId)
                .eq(Upvote::getBusinessType, businessType)
                .eq(Upvote::getCreatedId, loginId));
        if(count>0){
            return;
        }
        Long businessCreatedId;
        //点赞帖子
        if(BusinessTypeEnum.isArticle(businessType)){
            Article article = articleService.getById(businessId);
            businessCreatedId = article.getCreatedId();
        }else if(BusinessTypeEnum.isDiscuss(businessType)){
            //点赞评论
            Discuss discuss = discussService.getById(businessId);
            businessCreatedId = discuss.getCreatedId();

            //如果是点赞评论则维护评论表点赞数量字段
            discuss.setUpvoteCount(discuss.getUpvoteCount() + 1);
            discussService.updateById(discuss);
        }else{
            throw new ApiException(ResultCode.VALIDATE_FAILED);
        }

        Upvote upvote = new Upvote();
        upvote.setBusinessId(businessId);
        upvote.setBusinessType(businessType);
        upvote.setCreatedId(loginId);
        upvote.setBusinessCreatedId(businessCreatedId);
        save(upvote);
    }

    /**
     * 取消点赞
     * @param businessType 业务类型，ARTICLE,DISCUSS
     * @param businessId 业务id
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void cancel(String businessType,Long businessId) {
        Long loginId = authUtil.getUserId();

        LambdaQueryWrapper<Upvote> upvoteQuery = new LambdaQueryWrapper<>();
        upvoteQuery.eq(Upvote::getBusinessType, businessType);
        upvoteQuery.eq(Upvote::getBusinessId, businessId);
        upvoteQuery.eq(Upvote::getCreatedId, loginId);
        Upvote one = baseMapper.selectOne(upvoteQuery);
        if(one!=null){
            baseMapper.deleteById(one.getId());
        }

        //如果是取消点赞评论则维护评论表点赞数量字段
        if(BusinessTypeEnum.DISCUSS.getCode().equals(businessType)){
            Discuss discuss = discussService.getById(businessId);
            if(discuss.getUpvoteCount()>0) {
                discuss.setUpvoteCount(discuss.getUpvoteCount() - 1);
                discussService.updateById(discuss);
            }
        }
    }


    /**
     * 根据帖子id查询点赞数
     * @param businessType 业务类型，ARTICLE,DISCUSS
     * @param businessId 业务id
     * @return 点赞数量
     */
    @Override
    public Long queryUpvoteCount(String businessType,Long businessId) {
        return count(new LambdaQueryWrapper<Upvote>()
                .eq(Upvote::getBusinessId,businessId)
                .eq(Upvote::getBusinessType,businessType));
    }


    /**
     * 查询是否点赞
     *
     * @param businessType 业务类型，ARTICLE,DISCUSS
     * @param businessIds 业务id，业务类型为0时表示帖子id，业务类型为1时表示评论id
     * @return key:业务id value:是否点赞，true：已点赞 false:未点赞
     */
    @Override
    public Map<Long, Boolean> queryUpvote(String businessType,List<Long> businessIds) {

        List<Upvote> list = list(new LambdaQueryWrapper<Upvote>()
                .eq(Upvote::getCreatedId, authUtil.getUserId())
                .eq(Upvote::getBusinessType, businessType)
                .in(Upvote::getBusinessId, businessIds));
        //点赞过的帖子id
        List<Long> upvoteArticleIds = list.stream().map(Upvote::getBusinessId).collect(Collectors.toList());

        Map<Long,Boolean> result = new HashMap<>();
        businessIds.forEach(item ->{
            result.put(item,upvoteArticleIds.contains(item));
        });
        return result;
    }

    @Override
    public IPage<ArticleVo> upvotePage(UpvotePageDto dto) {
        Long customerId = dto.getCustomerId();
        if(customerId==null){
            customerId = authUtil.getUserId();
        }

        IPage<ArticleVo> page = Page.of(dto.getCurrent(), dto.getPageSize());
        LambdaQueryWrapper<Upvote> upvoteQuery = new LambdaQueryWrapper<>();
        upvoteQuery.eq(Upvote::getBusinessType, BusinessTypeEnum.ARTICLE.getCode());
        upvoteQuery.eq(Upvote::getCreatedId, customerId);
        IPage<Upvote> upvoteIPage = baseMapper.selectPage(Page.of(dto.getCurrent(), dto.getPageSize()), upvoteQuery);
        List<Upvote> records = upvoteIPage.getRecords();
        if(CollectionUtil.isEmpty(records)){
            return page;
        }
        page.setTotal(upvoteIPage.getTotal());

        Set<Long> articleIds = records.stream().map(Upvote::getBusinessId).collect(Collectors.toSet());
        List<ArticleVo> articleVoList = articleService.listVoByIds(articleIds);
        page.setRecords(articleVoList);
        return page;
    }
}
